﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DDD.Core {

    /// <summary>
    /// バウンディング ボックスをあらわす構造体
    /// </summary>
    /// <remarks>
    /// <see cref="BouindgBox"/> オブジェクトはバウンディング ボリュームの1種で、
    /// ノードを囲う軸に平行な６面の立方体です。
    /// バウンディング ボリュームの詳細については、<see cref="BoundingVolume"/> クラスの解説を参照してください。
    /// シーンをフリーズすると個々のノードのバウンディング ボリュームからバウンディング ボリューム階層が形成されます。
    /// バウンディング ボリューム階層の詳細については <see cref="World"/> クラスの解説を参照してください。
    /// ユーザーが <see cref="BoundingBox"/> 型を構造体をインスタンス化することはできず、
    /// 必ずエンジン側が作成したものを戻り値で受け取ります。
    /// アニメート可能、エクスポート可能。
    /// </remarks>
    public struct BoundingBox : IAnimatable<float>, IExportable<float> {

        /// <summary>
        /// コンストラクター
        /// </summary>
        /// <param name="minX">X軸の下限</param>
        /// <param name="maxX">X軸の上限</param>
        /// <param name="minY">Y軸の下限</param>
        /// <param name="maxY">Y軸の上限</param>
        /// <param name="minZ">Z軸の下限</param>
        /// <param name="maxZ">Z軸の上限</param>
        internal BoundingBox (float minX, float maxX, float minY, float maxY, float minZ, float maxZ)
            : this () {
            this.MinX = minX;
            this.MaxX = maxX;
            this.MinY = minY;
            this.MaxY = maxY;
            this.MinZ = minZ;
            this.MaxZ = maxZ;
        }

        /// <summary>
        /// 有効無効フラグ
        /// </summary>
        /// <remarks>
        /// このバウンディングボックスが有効なとき <c>true</c>を返し、そうでない時は <c>false</c>を返します。
        /// <note type="implement">
        /// 現在必ず <c>true</c> を返します。どういう用途で定義したのか忘れました。
        /// </note>
        /// </remarks>
        public bool IsValid {
            get { return true; }
        }

        /// <summary>
        /// X軸の下限
        /// </summary>
        /// <remarks>
        /// バウンディングボックスを形成するX軸方向の下限値です。
        /// </remarks>
        /// <value>X軸方向の下限値</value>
        public float MinX { get; private set; }

        /// <summary>
        /// X軸の上限
        /// </summary>
        /// <remarks>
        /// バウンディングボックスを形成するX軸方向の上限値です。
        /// </remarks>
        /// <value>X軸方向の上限値</value>
        public float MaxX { get; private set; }

        /// <summary>
        /// Y軸の下限
        /// </summary>
        /// <remarks>
        /// バウンディングボックスを形成するY軸方向の下限値です。
        /// </remarks>
        /// <value>Y軸方向の下限値</value>
        public float MinY { get; private set; }

        /// <summary>
        /// Y軸の上限
        /// </summary>
        /// <remarks>
        /// バウンディングボックスを形成するY軸方向の上限値です。
        /// </remarks>
        /// <value>Y軸方向の上限値</value>
        public float MaxY { get; private set; }

        /// <summary>
        /// Z軸の下限
        /// </summary>
        /// <remarks>
        /// バウンディングボックスを形成するY軸方向の下限値です。
        /// </remarks>
        /// <value>Y軸方向の下限値</value>
        public float MinZ { get; private set; }

        /// <summary>
        /// Z軸の上限
        /// </summary>
        /// <remarks>
        /// バウンディングボックスを形成するZ軸方向の上限値です。
        /// </remarks>
        /// <value>Z軸方向の上限値</value>
        public float MaxZ { get; private set; }

        /// <inheritdoc/>
        public int ComponentCount { get { return 6; } }

        /// <inheritdoc/>
        public float this[int index] {
            get {
                if (index < 0 || index > ComponentCount - 1) {
                    throw new IndexOutOfRangeException ();
                }
                return 0;
            }
            set {
                if (index < 0 || index > ComponentCount - 1) {
                    throw new IndexOutOfRangeException ();
                }
                
            }
        }

        /// <inheritdoc/>
        public override string ToString () {
            return string.Format ("BoundingBox: MinX={0}, MaxX={1}, MinY={2}, MaxY={3}, MinZ={4}, MaxZ={5}", MinX, MaxX, MinY, MaxY, MinZ, MaxZ);
        }
    }
}
